Amazon API Gateway + JWTオーソライザーでAzure ADのIDトークンクレームを表示してみた
いわさです。
ここ最近Azure ADのOIDC周りを少し触っています。
- Azure AD OIDCでUserInfoエンドポイントにアクセスする | DevelopersIO
- Azure ADのIDトークンを取得し、クレームを確認する | DevelopersIO
- Azure ADのIDトークンの署名を検証する | DevelopersIO
上記では自前で検証などしていたのですが、今回はAmazon API Gatewayとオーソライザーを使ったIDトークンの検証を行ってみたいと思います。
といっても、API GatewayにはJWTオーソライザーが提供されており、簡単に検証を行うことが出来ます。
JWTオーソライザーでは以下のようなJWTの基本的な検証機能を有しています。
- デコード
- 発行者のパブリックキーを使った署名の確認
- クレームの検証(kid, iss, aud, exp, nbf, iat, scope)
API Gateway + Lambda
組み込み対象のAPIを作成します。
バックエンド部分は一旦初期作成状態のLambda関数(Node14)とします。
exports.handler = async (event) => { // TODO implement const response = { statusCode: 200, body: JSON.stringify('Hello from Lambda!'), }; return response; };
API Gatewayと統合し、Postmanで呼び出してみます。
Lambdaのレスポンスを表示できていますね。
JWTオーソライザーを登録
では、オーソライザーを登録しましょう。
Lambdaオーソライザーでカスタム処理を作ることも出来ますが、JWT検証のみであればJWTオーソライザーを使うと車輪のなんとかをせずに済むってところなのでしょうか。
JWTオーソライザーの登録にあたって、以下を登録します。
- 発行者URL
- アプリケーションID(クライアントID)
ドキュメントのIssueからフォーマットを取得し、テナントIDを置き換えます。
{ "token_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token", "token_endpoint_auth_methods_supported": [ "client_secret_post", "private_key_jwt", "client_secret_basic" ], "jwks_uri": "https://login.microsoftonline.com/common/discovery/v2.0/keys", "response_modes_supported": [ "query", "fragment", "form_post" ], "subject_types_supported": [ "pairwise" ], "id_token_signing_alg_values_supported": [ "RS256" ], "response_types_supported": [ "code", "id_token", "code id_token", "id_token token" ], "scopes_supported": [ "openid", "profile", "email", "offline_access" ], "issuer": "https://login.microsoftonline.com/{tenantid}/v2.0", "request_uri_parameter_supported": false, "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", "device_authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/devicecode", "http_logout_supported": true, "frontchannel_logout_supported": true, "end_session_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/logout", "claims_supported": [ "sub", "iss", "cloud_instance_name", "cloud_instance_host_name", "cloud_graph_host_name", "msgraph_host", "aud", "exp", "iat", "auth_time", "acr", "nonce", "preferred_username", "name", "tid", "ver", "at_hash", "c_hash", "email" ], "kerberos_endpoint": "https://login.microsoftonline.com/common/kerberos", "tenant_region_scope": null, "cloud_instance_name": "microsoftonline.com", "cloud_graph_host_name": "graph.windows.net", "msgraph_host": "graph.microsoft.com", "rbac_url": "https://pas.windows.net" }
登録に必要なテナントIDとアプリケーションIDは以下より取得可能です。
テナントIDを専用のものに変更した発行者URLをオーソライザーへ登録します。
https://login.microsoftonline.com/9b9e2fc6-dc1a-4d7f-97ff-e86600ac5b48/v2.0
先程と同じようにアクセスしてみます。
認証エラーになりました!
IDトークンを渡す
では、IDトークンを使って作成したAPIへアクセスしてみましょう。
IDトークンの取得方法は以下の記事を参照してください。
JWT検証後、Lambdaバックエンドでクレームへアクセスすることが出来ます。(参考)
nameを取得してみましょう。
API Gateway は JWT を検証した後、トークン内のクレームを API ルートの統合に渡します。JWT クレームには、Lambda 関数などのバックエンドリソースがアクセスできます。
exports.handler = async (event) => { const response = { statusCode: 200, body: JSON.stringify(event.requestContext.authorizer.jwt.claims.name), }; return response; };
AuthorizationヘッダーにベアラートークンとしてIDトークンをセットしてリクエストを送信します。
検証を通過し、クレーム情報の取得に成功しました!
なお、不正なトークン(クライアントIDやテナントが異なるIDトークン、有効期限が切れたトークンなど)は401 Unauthorized
エラーとなることも確認出来ます。
まとめ
Azure ADに登録したアプリ情報を使って、JWTオーソライザーを構築してIDトークンの検証を行うことが出来ました。
カスタムLambdaでデコードして検証して、など行わなくて良いので楽ですね。